#include "stdafx.h"
#include <assert.h>
#include <xwt/xwt_window.h>

#ifdef WIN32
 extern HINSTANCE _hAppInstance;
#endif

xwt::Window::Window () {
	m_hWnd = NULL;
	m_isMainWnd = FALSE;
	m_isDialog = FALSE;
	m_userData = 0;
	m_flagMouseTracking = FALSE;
	m_opacity = 1.0f;
	m_bg_color.r = m_bg_color.g = m_bg_color.b = 250;
}

xwt::Window::~Window () {
	XWT_ASSERT (m_hWnd == NULL);
}

/* operations */
bool xwt::Window::Create (int x, int y, int cx, int cy, const sys_tchar *title) {
	XWT_ASSERT (m_hWnd == NULL);

#ifdef WIN32
	WNDCLASSEX wcex;
	memset (&wcex, 0, sizeof(wcex));

	// Fill in window class attributes that usually won't change	
	wcex.lpfnWndProc = _wndProc;
	wcex.hInstance = _hAppInstance;

	// get additional window class attributes
	GetClassStyle (wcex);

	// register the window class only onece	
	WNDCLASSEX dummyClassInfo;
	if (!::GetClassInfoEx (_hAppInstance, wcex.lpszClassName, &dummyClassInfo)) {
		RegisterClassEx (&wcex);
	}

	// get window creation styles
	DWORD dwStyle, dwExStyle;
	GetCreateStyle (dwStyle, dwExStyle);

	// create the window
	m_hWnd = ::CreateWindowEx ( dwExStyle, wcex.lpszClassName, title, dwStyle, 
								x, y, cx, cy, NULL, NULL, 
								wcex.hInstance, this );
	if (m_hWnd == NULL) {
		return false;
	}
#endif /* WIN32 */

	OnCreate ();

	return true;
}

void xwt::Window::Destroy () {
	XWT_ASSERT (m_hWnd != NULL);

#ifdef WIN32
	// Destroy the window. hWnd is set to NULL when WM_NCDESTROY 
	// message is received
	::DestroyWindow (m_hWnd);	
#endif
}

void xwt::Window::AttachHandle (HWND hWnd) {
	// handle can only be attached if window is not yet created
	XWT_ASSERT ( m_hWnd == NULL );

	// verify if the window is valid
#ifdef WIN32
	XWT_ASSERT ( ::IsWindow(hWnd) );
#endif /* WIN32 */

	m_hWnd = hWnd;
	
	MapHandle ();
}

xwt::XWTWND xwt::Window::DetachHandle () {
	XWT_ASSERT ( m_hWnd != NULL );

	XWTWND hDetached = m_hWnd;
	
	UnmapHandle();	
	
	m_hWnd = NULL;

	return hDetached;
}

void xwt::Window::Show () {
#ifdef WIN32
	::ShowWindow (m_hWnd, SW_SHOW);
	::UpdateWindow (m_hWnd);
#endif /* WIN32 */
}

void xwt::Window::Update () {
#ifdef WIN32
	::UpdateWindow (m_hWnd);
#endif
}

void xwt::Window::Hide () {
#ifdef WIN32
	XWT_ASSERT (
		::ShowWindow (m_hWnd, SW_HIDE)
		);
#endif
}

bool xwt::Window::IsValid () const {
#ifdef WIN32
	return m_hWnd && ::IsWindow (m_hWnd);
#endif
}

bool xwt::Window::IsVisible () const {
#ifdef WIN32
	return m_hWnd && ::IsWindowVisible (m_hWnd);
#endif
}

void xwt::Window::SetOpacity (float opacity) {
	m_opacity = (opacity < 0.0f 
				 ? 0.0f : 
				 (opacity > 1.0f ? 1.0f : opacity));

	if (GetHandle() != NULL ) {
		LONG wndLong = GetWindowLong(GetHandle(),GWL_EXSTYLE);

		if ( m_opacity == 1.0f ) {
			// set full opaque disable opacity...
			SetWindowLong (GetHandle(), GWL_EXSTYLE, (wndLong & ~WS_EX_LAYERED));
		 } else {
			// set new opacity level...		

			// Set WS_EX_LAYERED on this window 
			SetWindowLong (GetHandle(), GWL_EXSTYLE, wndLong | WS_EX_LAYERED);

			// Make this window 70% alpha
			SetLayeredWindowAttributes (GetHandle(), 0, int(m_opacity * 255), 
										LWA_ALPHA);	
		}
	}
}

void xwt::Window::AddChild (Window *pChildWnd) {
	XWT_ASSERT (
		this->IsValid()&& pChildWnd->IsValid ()
		);
	
#ifdef WIN32
	// First, set WS_CHILD style bit on the window to make a child
	LONG style = GetWindowLong ( pChildWnd->GetHandle(), GWL_STYLE );
	style|= WS_CHILD;
	::SetWindowLong ( pChildWnd->GetHandle(), GWL_STYLE, style );

	// set the parent to this window
	::SetParent ( pChildWnd->GetHandle(), m_hWnd );
#endif /* WIN32 */
}

xwt::Rect xwt::Window::GetWindowRect () const {
#ifdef WIN32
	RECT rt;
	XWT_ASSERT (
		::GetWindowRect (m_hWnd, &rt)
	);
#endif
	return ToXWTRect (rt);
}

xwt::Rect xwt::Window::GetClientRect () const {
#ifdef WIN32
	RECT rt;
	XWT_ASSERT (
		::GetClientRect (m_hWnd, &rt)
	);
	return ToXWTRect (rt);
#endif
}

void xwt::Window::Resize (const Rect &rect, bool force_repaint) {
#ifdef WIN32
	::MoveWindow ( GetHandle(), 
					rect.left, rect.top, 
					rect.width, rect.height, 
					force_repaint ? TRUE : FALSE 
					);
#endif
}

void xwt::Window::CenterWindow (Window *pParent) {
	XWTWND hWndParent = NULL;

	if (pParent) {
		hWndParent = pParent->GetHandle();
	}
	if (!hWndParent) {
		#ifdef WIN32
		hWndParent = ::GetDesktopWindow ();
		#endif
	}

	if (hWndParent) {
#ifdef WIN32
		RECT rectWnd, rectParent;
		::GetWindowRect ( m_hWnd, &rectWnd );
		::GetWindowRect ( hWndParent, &rectParent );

		POINT offset;

 		offset.x = rectParent.left + 
					(rectParent.right - rectParent.left) / 2 - 
					(rectWnd.right - rectWnd.left) / 2;

		offset.y =  rectParent.top + 
					(rectParent.bottom - rectParent.top) / 2 - 
					(rectWnd.bottom - rectWnd.top) / 2;

		::MoveWindow (m_hWnd, offset.x, offset.y, rectWnd.right - rectWnd.left,
						rectWnd.bottom - rectWnd.top, 
						IsWindowVisible(m_hWnd) );
#endif
	}
}

void xwt::Window::SetBackgroundColor (const Color &clr) {
	m_bg_color = clr;
}

void xwt::Window::SetTitleText (sys_tchar *text) {
#ifdef WIN32
	::SetWindowText (m_hWnd, text);
#endif
}

void xwt::Window::EnableDropTarget (bool flag_enable, unsigned max) {
#ifdef WIN32
	::DragAcceptFiles (m_hWnd, flag_enable);	
#endif
	m_dropTargetMax = max;
}

/* helpers */
inline void xwt::Window::MapHandle () {
#ifdef WIN32
	::SetWindowLongPtr (m_hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)this);
#endif
}

inline void xwt::Window::UnmapHandle () {
#ifdef WIN32
	::SetWindowLongPtr ( m_hWnd , GWLP_USERDATA, 0L );
#endif
}

// overridables...

#ifdef WIN32
void xwt::Window::GetCreateStyle (DWORD &dwStyle, DWORD &dwExStyle) {
	dwStyle = WS_OVERLAPPEDWINDOW;
	dwExStyle = 0;
}
#endif

#ifdef WIN32
/**
 * Fill in the default window class style attributes.
 * Window class name must be changed in the lpszClassName member if overriden
 * for custom style attributes and all attributes below must be filled in.
 */
void xwt::Window::GetClassStyle (WNDCLASSEX &wcex) {
	wcex.lpszClassName = _T("_gls_window");
	wcex.cbSize = sizeof(wcex);
	wcex.style = 0; // CS_HREDRAW | CS_VREDRAW;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hIcon = LoadIcon (NULL, IDI_APPLICATION);
	wcex.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
	wcex.hCursor = LoadCursor (NULL, IDC_ARROW);
	wcex.hbrBackground =  NULL; // CreateSolidBrush(RGB(100,100,100));
	wcex.lpszMenuName = NULL;
	wcex.hInstance = _hAppInstance;
}
#endif

#ifdef WIN32
LRESULT xwt::Window::HandleMessage (UINT msg, WPARAM wParam, LPARAM lParam) {
	LRESULT ret = FALSE;

	switch (msg) {	
	case WM_MOUSEMOVE:
		ret = _WM_MOUSEMOVE_handler (wParam, lParam);
		break;
	case WM_MOUSELEAVE:
		ret = _WM_MOUSELEAVE_handler (wParam, lParam);
		break;
	case WM_LBUTTONDOWN:
		ret = _WM_LBUTTONDOWN_handler (wParam, lParam);
		break;
	case WM_LBUTTONUP:
		ret = _WM_LBUTTONUP_handler (wParam, lParam);
		break;
	case WM_RBUTTONDOWN:
		ret = _WM_RBUTTONDOWN_handler (wParam, lParam);
		break;
	case WM_RBUTTONUP:
		ret = _WM_RBUTTONUP_handler (wParam, lParam);
		break;
	case WM_ERASEBKGND:
		ret = _WM_ERASEBKGND_handler (wParam, lParam);
		break;
	case WM_PAINT:
		ret = _WM_PAINT_handler (wParam, lParam);
		break;
	case WM_CHAR:
		ret = _WM_CHAR_handler (wParam, lParam);
		break;
	case WM_KEYDOWN:
		ret = _WM_KEYDOWN_handler (wParam, lParam);
		break;
	case WM_KEYUP:
		ret = _WM_KEYUP_handler (wParam, lParam);
		break;
	case WM_NCDESTROY:
		ret = _WM_NCDESTROY_handler (wParam, lParam);
		break;
	case WM_DESTROY:
		ret = _WM_DESTROY_handler (wParam, lParam);
		break;
	case WM_SIZE:
		ret = _WM_SIZE_handler (wParam, lParam);
		break;
	case WM_SETFOCUS:
		ret = _WM_SETFOCUS_handler (wParam, lParam);
		break;
	case WM_KILLFOCUS:
		ret = _WM_KILLFOCUS_handler (wParam, lParam);
		break;
	case WM_COMMAND:
		ret = _WM_COMMAND_handler (wParam, lParam);
		break;
	case WM_CONTEXTMENU:
		ret = _WM_CONTEXTMENU_handler (wParam, lParam);
		break;
	case WM_CLOSE:
		ret = _WM_CLOSE_handler (wParam, lParam);
		break;
	case WM_DROPFILES:
		ret = _WM_DROPFILES_handler (wParam, lParam);
		break;
	default:
		ret = ::DefWindowProc (m_hWnd, msg, wParam, lParam);
	}

	return ret;
}
#endif

#ifdef WIN32
INT_PTR xwt::Window::HandleDialogMessage (UINT msg, WPARAM wParam, LPARAM lParam) {
	INT_PTR ret = FALSE;

	switch (msg) {	
	case WM_MOUSEMOVE:
		ret = _DLG_WM_MOUSEMOVE_handler (wParam, lParam);
		break;
	case WM_MOUSELEAVE:
		ret = _DLG_WM_MOUSELEAVE_handler (wParam, lParam);
		break;
	case WM_LBUTTONDOWN:
		ret = _DLG_WM_LBUTTONDOWN_handler (wParam, lParam);
		break;
	case WM_LBUTTONUP:
		ret = _DLG_WM_LBUTTONUP_handler (wParam, lParam);
		break;
	case WM_RBUTTONDOWN:
		ret = _DLG_WM_RBUTTONDOWN_handler (wParam, lParam);
		break;
	case WM_RBUTTONUP:
		ret = _DLG_WM_RBUTTONUP_handler (wParam, lParam);
		break;
	case WM_CHAR:
		ret = _DLG_WM_CHAR_handler (wParam, lParam);
		break;
	case WM_KEYDOWN:
		ret = _DLG_WM_KEYDOWN_handler (wParam, lParam);
		break;
	case WM_KEYUP:
		ret = _DLG_WM_KEYUP_handler (wParam, lParam);
		break;
	case WM_NCDESTROY:
		ret = _DLG_WM_NCDESTROY_handler (wParam, lParam);
		break;
	case WM_DESTROY:
		ret = _DLG_WM_DESTROY_handler (wParam, lParam);
		break;
	case WM_SIZE:
		ret = _DLG_WM_SIZE_handler (wParam, lParam);
		break;
	case WM_SETFOCUS:
		ret = _DLG_WM_SETFOCUS_handler (wParam, lParam);
		break;
	case WM_KILLFOCUS:
		ret = _DLG_WM_KILLFOCUS_handler (wParam, lParam);
		break;
	case WM_COMMAND:
		ret = _DLG_WM_COMMAND_handler (wParam, lParam);
		break;
	case WM_CONTEXTMENU:
		ret = _DLG_WM_CONTEXTMENU_handler (wParam, lParam);
		break;
	case WM_INITDIALOG:
		ret = _DLG_WM_INITDIALOG_handler (wParam, lParam);
		break;
	case WM_ERASEBKGND:
		ret = _DLG_WM_ERASEBKGND_handler (wParam, lParam);
		break;
	case WM_PAINT:
		ret = _DLG_WM_PAINT_handler (wParam, lParam);
		break;
	default:
		ret = FALSE;		
	}

	return ret;
}
#endif /* WIN32 */

// static 
#ifdef WIN32
LRESULT CALLBACK xwt::Window::_wndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	Window *pWnd = NULL;

	if (msg == WM_CREATE) {
		// get Window object
		CREATESTRUCT *cs = (CREATESTRUCT *) lParam;
		pWnd = (Window *)cs->lpCreateParams;
		XWT_ASSERT (pWnd);

		// bind HWND with the Sim8085IdeWindow object 
		::SetWindowLongPtr ( hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)pWnd);
	} else {
		// get window object from window handle
		LONG_PTR ptr = ::GetWindowLongPtr (hWnd, GWLP_USERDATA);
		pWnd = (Window *) ptr;
	}

	if (pWnd) {
		return pWnd->HandleMessage (msg, wParam, lParam);
	}

	return ::DefWindowProc (hWnd, msg, wParam, lParam);
}

// static 
INT_PTR xwt::Window::_dlgProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	Window *pThis = NULL;

	if (msg == WM_INITDIALOG) {			
		// map dialog window handle to its Window object
		pThis = (Window *) lParam;		
		::SetWindowLongPtr ( hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)pThis);
		pThis->m_hWnd = hWnd;
	}
	else {
		// get window object from window handle
		LONG_PTR ptr = ::GetWindowLongPtr (hWnd, GWLP_USERDATA);
		pThis = (Window *) ptr;
	}

	if (pThis) {
		return pThis->HandleDialogMessage (msg, wParam, lParam);
	}

	return FALSE;
}
#endif /* WIN32 */

// default window message handlers...
#ifdef WIN32

LRESULT xwt::Window::_WM_MOUSEMOVE_handler (WPARAM wParam, LPARAM lParam) {
	if (!m_flagMouseTracking) {
		// register for mouse out message (TME_LEAVE)
		TRACKMOUSEEVENT trackMouseEvent;
		
		trackMouseEvent.cbSize = sizeof (trackMouseEvent);
		trackMouseEvent.dwFlags = TME_LEAVE;
		trackMouseEvent.dwHoverTime = 0;
		trackMouseEvent.hwndTrack = GetHandle ();

		m_flagMouseTracking = ::TrackMouseEvent (&trackMouseEvent) 
								? true : false;
	}

	OnMouseMove (InvalidButton, LOWORD(lParam), HIWORD(lParam));
	return FALSE;
}

LRESULT xwt::Window::_WM_MOUSELEAVE_handler (WPARAM wParam, LPARAM lParam) {
	m_flagMouseTracking = FALSE;
	OnMouseLeave ();
	return FALSE;
}

LRESULT xwt::Window::_WM_LBUTTONDOWN_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseDown (LeftButton, LOWORD(lParam), HIWORD(lParam));
	return FALSE;
}

LRESULT xwt::Window::_WM_LBUTTONUP_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseUp (LeftButton, LOWORD(lParam), HIWORD(lParam));
	return FALSE;
}

LRESULT xwt::Window::_WM_RBUTTONDOWN_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseDown (RightButton, LOWORD(lParam), HIWORD(lParam));
	return FALSE;
}

LRESULT xwt::Window::_WM_RBUTTONUP_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseUp (RightButton, LOWORD(lParam), HIWORD(lParam));
	return FALSE;
}

LRESULT xwt::Window::_WM_ERASEBKGND_handler (WPARAM wParam, LPARAM lParam) {
	// we'll erase the background during the WM_PAINT message as necessary
	// to support dynamic background color for views
	// return FALSE to indicate we didn't erase the background here.
	return FALSE;
}

LRESULT xwt::Window::_WM_PAINT_handler (WPARAM wParam, LPARAM lParam) {
	GC *gc = GC::CreatePaintGC (GetHandle());

	// erase the background if required
	if (gc->ShouldEraseBackground ()) {
		OnEraseBackground (*gc);
		gc->UpdateEraseBackgroundFlag (false);
	}

	OnPaint (*gc);

	delete gc;
	return FALSE;
}

LRESULT xwt::Window::_WM_CHAR_handler (WPARAM wParam, LPARAM lParam) {
	OnKeyPress ( (int)wParam, LOWORD(lParam) );
	return FALSE;
}

LRESULT xwt::Window::_WM_KEYDOWN_handler (WPARAM wParam, LPARAM lParam) {
	OnKeyDown ( (int)wParam );
	return FALSE;
}

LRESULT xwt::Window::_WM_KEYUP_handler (WPARAM wParam, LPARAM lParam) {
	OnKeyUp ( (int)wParam );
	return FALSE;
}

LRESULT xwt::Window::_WM_NCDESTROY_handler (WPARAM wParam, LPARAM lParam) {
	OnPreDestroy ();
	m_hWnd = NULL;
	return FALSE;
}

LRESULT xwt::Window::_WM_DESTROY_handler (WPARAM wParam, LPARAM lParam) {
	OnDestroy ();
	if (m_isMainWnd) {
		::PostQuitMessage (0);
	}
	return FALSE;
}

LRESULT xwt::Window::_WM_SIZE_handler (WPARAM wParam, LPARAM lParam) {
	int cx, cy;
	cx = LOWORD(lParam);
	cy = HIWORD(lParam);
	OnResize (cx, cy);
	return FALSE;
}

LRESULT xwt::Window::_WM_SETFOCUS_handler (WPARAM wParam, LPARAM lParam) {
	OnGotFocus ();
	return FALSE;
}

LRESULT xwt::Window::_WM_KILLFOCUS_handler (WPARAM wParam, LPARAM lParam) {
	OnLostFocus ();
	return FALSE;
}

LRESULT xwt::Window::_WM_COMMAND_handler (WPARAM wParam, LPARAM lParam) {
	OnCommand ( LOWORD(wParam) );
	return FALSE;
}

LRESULT xwt::Window::_WM_CONTEXTMENU_handler (WPARAM wParam, LPARAM lParam) {
	OnContextMenu ( );
	return FALSE;
}

LRESULT xwt::Window::_WM_CLOSE_handler (WPARAM wParam, LPARAM lParam) {
	bool cancel = FALSE;
	OnClose (cancel);
	if (cancel == FALSE) {
		DestroyWindow (m_hWnd);
	}
	return FALSE;
}

LRESULT xwt::Window::_WM_DROPFILES_handler (WPARAM wParam, LPARAM lParam) {
	std::list<tstring> list_dropped_files;

	const UINT QUERY_FILE_COUNT = 0xFFFFFFFF;

	HDROP hdrop = NULL; // #TODO: init hdrop

	// first, query for the number of files dropped
	UINT count_files_dropped = DragQueryFile (hdrop, QUERY_FILE_COUNT, NULL, 0);

	for (UINT i = 0; i < count_files_dropped; i++) {
		// query for the size of buffer requierd to store the file path
		UINT file_path_length = DragQueryFile (hdrop, 0, NULL, 0);

		file_path_length++; // for '\0' character

		// allocate buffer file file path
		TCHAR *file_path = new TCHAR [file_path_length];

		// retrieve the file path now
		DragQueryFile (hdrop, 0, file_path, file_path_length);

		// add file name to list
		tstring str_file_path(file_path);
		list_dropped_files.push_back (str_file_path);

		delete file_path;
	}

	// process the file now...
	OnDropFiles (list_dropped_files);

	return FALSE;
}

#endif /* WIN32 window message handlers... */


// dialog box message handlers...
#ifdef WIN32

INT_PTR xwt::Window::_DLG_WM_MOUSEMOVE_handler (WPARAM wParam, LPARAM lParam) {
	if (!m_flagMouseTracking) {
		// register for mouse out message (TME_LEAVE)
		TRACKMOUSEEVENT trackMouseEvent;
		trackMouseEvent.cbSize = sizeof (trackMouseEvent);
		trackMouseEvent.dwFlags = TME_LEAVE;
		trackMouseEvent.dwHoverTime = 0;
		trackMouseEvent.hwndTrack = GetHandle ();
		m_flagMouseTracking = ::TrackMouseEvent (&trackMouseEvent) ? true : false;
	}
	OnMouseMove (InvalidButton, LOWORD(lParam), HIWORD(lParam));
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_MOUSELEAVE_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseLeave ();
	m_flagMouseTracking = FALSE;
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_LBUTTONDOWN_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseDown (LeftButton, LOWORD(lParam), HIWORD(lParam));
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_LBUTTONUP_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseUp (LeftButton, LOWORD(lParam), HIWORD(lParam));
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_RBUTTONDOWN_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseDown (RightButton, LOWORD(lParam), HIWORD(lParam));
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_RBUTTONUP_handler (WPARAM wParam, LPARAM lParam) {
	OnMouseUp (RightButton, LOWORD(lParam), HIWORD(lParam));
	OnContextMenu ( );
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_CHAR_handler (WPARAM wParam, LPARAM lParam) {
	OnKeyPress ( (int)wParam, LOWORD(lParam) );
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_KEYDOWN_handler (WPARAM wParam, LPARAM lParam) {
	OnKeyDown ( (int)wParam );
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_KEYUP_handler (WPARAM wParam, LPARAM lParam) {
	OnKeyUp ( (int)wParam );
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_NCDESTROY_handler (WPARAM wParam, LPARAM lParam) {
	OnPreDestroy ();
	m_hWnd = NULL;
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_DESTROY_handler (WPARAM wParam, LPARAM lParam) {
	OnDestroy ();
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_SIZE_handler (WPARAM wParam, LPARAM lParam) {
	int cx, cy;
	cx = LOWORD(lParam);
	cy = HIWORD(lParam);
	OnResize (cx, cy);
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_SETFOCUS_handler (WPARAM wParam, LPARAM lParam) {
	OnGotFocus ();
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_KILLFOCUS_handler (WPARAM wParam, LPARAM lParam) {
	OnLostFocus ();
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_COMMAND_handler (WPARAM wParam, LPARAM lParam) {
	OnCommand ( LOWORD(wParam) );
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_CONTEXTMENU_handler (WPARAM wParam, LPARAM lParam) {
	OnContextMenu ();
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_INITDIALOG_handler (WPARAM wParam, LPARAM lParam) {
	OnInitDialog ();
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_ERASEBKGND_handler (WPARAM wParam, LPARAM lParam) {
	return TRUE;
}

INT_PTR xwt::Window::_DLG_WM_PAINT_handler (WPARAM wParam, LPARAM lParam) {
	GC *gc = GC::CreatePaintGC (GetHandle());

	// erase the background if required
	if (gc->ShouldEraseBackground ()) {
		OnEraseBackground (*gc);
		gc->UpdateEraseBackgroundFlag (false);
	}

	OnPaint (*gc);
	delete gc;

	return TRUE;
}

#endif /* WIN32 dialog box message handlers... */

// default event handlers...

void xwt::Window::OnCreate () {
	SetOpacity (m_opacity);
}

void xwt::Window::OnEraseBackground (GC &gc) {
	Rect rect = GetClientRect ();
	gc.SetPenColor (m_bg_color);
	gc.SetFillColor (m_bg_color);
	gc.Rectangle (rect.left, rect.top, rect.width, rect.height);
}

void xwt::Window::OnCommand (int cmdId) {
	if (!m_isMainWnd) {
	#ifdef WIN32
		// forward command messages upwards in the window hierarchy
		::SendMessage ( GetParentHandle(), WM_COMMAND, (WPARAM)cmdId, 0 );
	#endif
	}
}
